/*
 *  (c) 2015 fullhan.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

/*****************************************************************************
 *  Include Section
 *  add all #include here
 *****************************************************************************/
#include "tuning_lib.h"
/*****************************************************************************
 * Define section
 * add all #define here
 *****************************************************************************/

/*****************************************************************************
 * func below..
 *****************************************************************************/
//auto tuning ref below
void dl_info_init(struct tuning_dl_info *p_info, int rec_dl_size){
	int i;

	for (i = 0; i < rec_dl_size; i++) {
		memset(&p_info[i], 0, sizeof(struct tuning_dl_info));
		p_info[i].result = "fail";
	}
}

void dump_dl_info(struct tuning_dl_info *p_info, int rec_dl_size)
{
	int i = 0;
	printf("----------GAP LINE----------\n");
	for (i = 0; i < rec_dl_size; i++)
		printf("[index %04d] :: tx[%04x] : rx[%04x] = %s\n",i,
		p_info[i].tx_dl, p_info[i].rx_dl, p_info[i].result);
}


void dump_dl_result(struct tuning_result_info *p_info)
{

	printf("[Result] :: is %s\n",
	p_info->tx_or_rx == TUNING_PARSE_TX_DL_REC ? "Tx" : "Rx");
	printf("[Win] :: from [%04d] to [%04d] . total len [%04d]\n",
	p_info->pass_win_st, p_info->pass_win_ed, p_info->pass_win_len);
	printf("[Mid] :: is 0x%x\n",p_info->pass_mid_ret);
	if(p_info->p_dl_st)
		printf("[Sta info] :: tx[%04x] : rx[%04x] = %s\n",
		p_info->p_dl_st->tx_dl, p_info->p_dl_st->rx_dl, p_info->p_dl_st->result);
	if(p_info->p_dl_mid)
		printf("[Mid info] :: tx[%04x] : rx[%04x] = %s\n",
		p_info->p_dl_mid->tx_dl, p_info->p_dl_mid->rx_dl, p_info->p_dl_mid->result);
	if(p_info->p_dl_end)
		printf("[End info] :: tx[%04x] : rx[%04x] = %s\n",
		p_info->p_dl_end->tx_dl, p_info->p_dl_end->rx_dl, p_info->p_dl_end->result);

}

int tuning_parse_dl_rec(struct tuning_dl_info *p_info, int rec_dl_size,
struct tuning_result_info *p_ret_info){

	int i;
	int state = TUNING_STATE_REC_DATA_HI;
	struct tuning_dl_info *raw_p_info;
	int best_index;
	int fin_win_hi = TUNING_INIT_TEST_DATA;
	int fin_win_lo = TUNING_INIT_TEST_DATA;
	int new_win_hi = TUNING_INIT_TEST_DATA;
	int new_win_lo = TUNING_INIT_TEST_DATA;
	raw_p_info = p_info;

	for (i = 0; i < rec_dl_size; i++, p_info++) {
		switch (state) {
		case TUNING_STATE_REC_DATA_HI:
			if (strcmp(p_info->result, "pass") == 0) {
				//maybe last is pass..
				new_win_hi = i;
				state = TUNING_STATE_REC_DATA_LO;
			}
		break;
		case TUNING_STATE_REC_DATA_LO:
			if (strcmp(p_info->result, "pass") != 0) {
				/*if fail, last must be pass*/
				new_win_lo = i - 1;
				state = TUNING_STATE_REC_DATA_HI;
				/*if new win > old win, just rec max win*/
				if ((new_win_lo - new_win_hi) >=
				(fin_win_lo - fin_win_hi)) {
					fin_win_hi = new_win_hi;
					fin_win_lo = new_win_lo;
				}
			}
		break;
		default:
			printf("unknow state %x\n", state);
			//bugon is better.
			break;
		}
	}
	/*only find one pass...no fail at last..*/
	if ((new_win_hi != TUNING_INIT_TEST_DATA)  && (new_win_lo == TUNING_INIT_TEST_DATA)) {
		// printf("got one pass, no fail to end..pass index[%d]\n",
		// new_win_hi);

		p_ret_info->pass_win_st = new_win_hi;
		p_ret_info->pass_win_ed = rec_dl_size - 1;
		p_ret_info->pass_win_len = rec_dl_size - new_win_hi;
		best_index = (rec_dl_size - new_win_hi) / 2;
		best_index += new_win_hi;
	//	printf("best data index is 0x%x\n", best_index);
		if(p_ret_info->tx_or_rx == TUNING_PARSE_TX_DL_REC)
			p_ret_info->pass_mid_ret = raw_p_info[best_index].tx_dl;
		else
			p_ret_info->pass_mid_ret = raw_p_info[best_index].rx_dl;
		
		p_ret_info->p_dl_st = &raw_p_info[p_ret_info->pass_win_st];
		p_ret_info->p_dl_mid = &raw_p_info[best_index];
		p_ret_info->p_dl_end = &raw_p_info[p_ret_info->pass_win_ed];
		return 0;
	}

	/*all failed...*/
	if ((new_win_hi == TUNING_INIT_TEST_DATA)  && (new_win_lo == TUNING_INIT_TEST_DATA)) {
		//printf("all failed !!!!\n");
		p_ret_info->p_dl_st = 0;
		p_ret_info->p_dl_mid = 0;
		p_ret_info->p_dl_end = 0;
		return -1;
	}

	best_index = (fin_win_lo - fin_win_hi + 1) / 2;
	p_ret_info->pass_win_len = fin_win_lo - fin_win_hi + 1;
	best_index += fin_win_hi;
	if(p_ret_info->tx_or_rx == TUNING_PARSE_TX_DL_REC)
		p_ret_info->pass_mid_ret = raw_p_info[best_index].tx_dl;
	else
		p_ret_info->pass_mid_ret = raw_p_info[best_index].rx_dl;

	p_ret_info->pass_win_st = fin_win_hi;
	p_ret_info->pass_win_ed = fin_win_lo;
	p_ret_info->p_dl_st = &raw_p_info[p_ret_info->pass_win_st];
	p_ret_info->p_dl_mid = &raw_p_info[best_index];
	p_ret_info->p_dl_end = &raw_p_info[p_ret_info->pass_win_ed];
	return 0;
}
